﻿using System;
using System.Collections.Generic;
using System.Configuration;
using MSAcademic.v2.Database;
using System.Linq;

using MSAcademic.v2.Infrastructure.AccessRights;
using MSAcademic.v2.Infrastructure.SubSection;
using MSAcademic.v2.Infrastructure.SubSection.Impl;
using MSAcademic.v2.Infrastructure.Tag;
using MSAcademic.v2.Infrastructure.Tag.Impl;
using MSAcademic.v2.Infrastructure.User;

namespace MSAcademic.v2.Infrastructure.Article.Impl
{
    public partial class ArticleQueriesImpl : IArticleQueries
    {

        public IArticle GetArticle(int articleId)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                var article = db.Articles.SingleOrDefault(m => m.Id == articleId);
                if (article != null)
                {
                    return new ArticleImpl(article);
                }
            }
            return null;
        }

        public IEnumerable<IArticle> GetLatestArticlesPaged(int page, bool showHidden, IUser signedInUser)
        {
            var numberOfArticles = Convert.ToInt32(ConfigurationManager.AppSettings["AdminArticleIndexListCount"]);

            using (var database = new MSAcademicDatabaseContainer())
            {
                var canUserViewAll = _accessRightsService.CanUserAccess(signedInUser, AccessRight.CanViewAll);

                var data = database.Articles.Where(x =>
                                                (!x.IsHidden || showHidden)
                                                && (canUserViewAll
                                                || signedInUser.Id == x.UserId))
                                            .OrderByDescending(x => x.CreatedOn)
                                            .Skip((page - 1) * numberOfArticles)
                                            .Take(numberOfArticles)
                                            .Select(article => new ArticleImpl()
                                                {
                                                    Id = article.Id,
                                                    Title = article.Title,
                                                    ShortText = article.ShortText,
                                                    LongText = article.LongText,
                                                    IsHidden = article.IsHidden,
                                                    CreatedOn = article.CreatedOn,
                                                    PublishedOn = article.PublishedOn,
                                                    PictureUrlBig = article.PictureUrlBig,
                                                    PictureUrlNormal = article.PictueUrlNormal,
                                                    PictureUrlThumbnail = article.PictureUrlThumbnail,
                                                    UserId = article.UserId
                                                })
                                            .ToList();
                return data;
            }
        }

        public int GetNumberOfPages(bool countHidden)
        {
            using (var database = new MSAcademicDatabaseContainer())
            {
                var numberOfArticlesPerPage = Convert.ToDouble(ConfigurationManager.AppSettings["AdminArticleIndexListCount"]);
                var numberOfArticles = (double)database.Articles.Count(x => (!x.IsHidden || countHidden));
                return (int)Math.Ceiling(numberOfArticles / numberOfArticlesPerPage);
            }
        }

        public IEnumerable<ITag> GetTagsForArticle(int id)
        {
            using (var database = new MSAcademicDatabaseContainer())
            {
                var article = database.Articles.SingleOrDefault(x => x.Id == id);
                if (article == null) return null;

                var tags = article.Tags.Select(x => new TagImpl { Id = x.Id, Name = x.Name }).ToList();
                return tags;
            }
        }

        public IEnumerable<ISubSection> GetSubSectionsForArticle(int articleId, bool showHidden)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                var article = db.Articles.SingleOrDefault(m => m.Id == articleId);
                if (article == null) return null;
                var subsections = article.SubSections.Where(m => m.IsHidden == showHidden).Select(m => new SubSectionImpl { Id = m.Id, ContentSectionId = m.ContentSectionId, IsHidden = m.IsHidden, Name = m.Name, ThumbnailUrl = m.ThumbnailUrl }).ToList();
                return subsections;
            }
        }

        public IEnumerable<IArticle> GetArticlesForSubSection(int subSectionId)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                var subSec = db.SubSections.SingleOrDefault(x => x.Id == subSectionId);
                if (subSec == null) return null;

                return subSec.Articles.Where(x => !x.IsHidden && x.PublishedOn.HasValue)
                                      .Select(article => new ArticleImpl
                                        {
                                            Id = article.Id,
                                            Title = article.Title,
                                            ShortText = article.ShortText,
                                            LongText = article.LongText,
                                            IsHidden = article.IsHidden,
                                            CreatedOn = article.CreatedOn,
                                            PublishedOn = article.PublishedOn,
                                            PictureUrlBig = article.PictureUrlBig,
                                            PictureUrlNormal = article.PictueUrlNormal,
                                            PictureUrlThumbnail = article.PictureUrlThumbnail,
                                            UserId = article.UserId
                                        }).OrderByDescending(x => x.PublishedOn).ToList();
            }
        }

        public IEnumerable<IArticle> GetLatestArticles(int count)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                return db.Articles.Where(x => !x.IsHidden && x.PublishedOn.HasValue)
                                  .Take(count)
                                  .Select(article => new ArticleImpl
                                  {
                                      Id = article.Id,
                                      Title = article.Title,
                                      ShortText = article.ShortText,
                                      LongText = article.LongText,
                                      IsHidden = article.IsHidden,
                                      CreatedOn = article.CreatedOn,
                                      PublishedOn = article.PublishedOn,
                                      PictureUrlBig = article.PictureUrlBig,
                                      PictureUrlNormal = article.PictueUrlNormal,
                                      PictureUrlThumbnail = article.PictureUrlThumbnail,
                                      UserId = article.UserId
                                  }).OrderByDescending(x => x.PublishedOn).ToList();
            }
        }

        public IEnumerable<IArticle> GetArticlesForSubSectionsWithTagFilter(List<int> tagsToSearchFor, int subsectionId, bool showHidden)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                var subsection = db.SubSections.SingleOrDefault(m => m.Id == subsectionId);

                if (subsection == null) return null;

                var articlesInSubSection = subsection.Articles.Where(m => m.Tags.Any(x => tagsToSearchFor.Contains(x.Id)) && m.IsHidden == showHidden && m.PublishedOn.HasValue).
                    OrderByDescending(m => m.PublishedOn).Select(m => new ArticleImpl
                                                                                  {
                                                                                      CreatedOn = m.CreatedOn,
                                                                                      Id = m.Id,
                                                                                      IsHidden = m.IsHidden,
                                                                                      LongText = m.LongText,
                                                                                      PictureUrlBig = m.PictureUrlBig,
                                                                                      PictureUrlNormal = m.PictueUrlNormal,
                                                                                      PictureUrlThumbnail = m.PictureUrlThumbnail,
                                                                                      PublishedOn = m.PublishedOn,
                                                                                      ShortText = m.ShortText,
                                                                                      Title = m.Title,
                                                                                      UserId = m.UserId
                                                                                  }).ToList();
                return articlesInSubSection;

            }
        }

        public IEnumerable<IArticle> GetArticlesForContentSection(int contentSectionId)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                var contentSection = db.ContentSections.SingleOrDefault(m => m.Id == contentSectionId);
                var subsection = contentSection.SubSections.ToList();

                var list = new List<IArticle>();
                foreach (var subSection in subsection)
                {
                    list.AddRange(subSection.Articles.Select(article => new ArticleImpl
                                                                            {
                                                                                CreatedOn = article.CreatedOn,
                                                                                Id = article.Id,
                                                                                IsHidden = article.IsHidden,
                                                                                LongText = article.LongText,
                                                                                PictureUrlBig = article.PictureUrlBig,
                                                                                PictureUrlNormal = article.PictueUrlNormal,
                                                                                PictureUrlThumbnail = article.PictureUrlThumbnail,
                                                                                PublishedOn = article.PublishedOn,
                                                                                ShortText = article.ShortText,
                                                                                Title = article.Title,
                                                                                UserId = article.UserId
                                                                            }).Cast<IArticle>());
                }


                return list;
            }

        }

        public IEnumerable<IArticle> GetArticlesWrittenByAuthor(int authorId, bool showHidden)
        {
            using (var db = new MSAcademicDatabaseContainer())
            {
                var authorsArticles = db.Articles.Where(article => article.UserId == authorId && article.IsHidden == showHidden && article.PublishedOn.HasValue)
                                                 .Select(article => new ArticleImpl
                                                                                    {
                                                                                        CreatedOn = article.CreatedOn,
                                                                                        Id = article.Id,
                                                                                        IsHidden = article.IsHidden,
                                                                                        LongText = article.LongText,
                                                                                        PictureUrlBig = article.PictureUrlBig,
                                                                                        PictureUrlNormal = article.PictueUrlNormal,
                                                                                        PictureUrlThumbnail = article.PictureUrlThumbnail,
                                                                                        PublishedOn = article.PublishedOn,
                                                                                        ShortText = article.ShortText,
                                                                                        Title = article.Title,
                                                                                        UserId = article.UserId
                                                                                    }).ToList();

                return authorsArticles;
            }
        }

        public IEnumerable<IArticle> GetArticlesForSubSectionName(string subSectionName, bool showHidden)
        {
            var numberOfArticles = Convert.ToInt32(ConfigurationManager.AppSettings["FeaturedArticleIndexCount"]);
            using (var db = new MSAcademicDatabaseContainer())
            {
                return db.Articles.Where(x => x.SubSections.Any(z => z.Name == subSectionName) && (!x.IsHidden || showHidden))
                                  .Select(article => new ArticleImpl
                                  {
                                      Id = article.Id,
                                      Title = article.Title,
                                      ShortText = article.ShortText,
                                      LongText = article.LongText,
                                      IsHidden = article.IsHidden,
                                      CreatedOn = article.CreatedOn,
                                      PublishedOn = article.PublishedOn,
                                      PictureUrlBig = article.PictureUrlBig,
                                      PictureUrlNormal = article.PictueUrlNormal,
                                      PictureUrlThumbnail = article.PictureUrlThumbnail,
                                      UserId = article.UserId
                                  }).OrderByDescending(x => x.PublishedOn)
                                    .Take(numberOfArticles)
                                    .ToList();

            }

        }
    }

    public partial class ArticleQueriesImpl
    {
        private readonly IAccessRightsService _accessRightsService;

        public ArticleQueriesImpl(
            IAccessRightsService accessRightsService)
        {
            _accessRightsService = accessRightsService;
        }
    }
}
